package cpre556.project2.eclipsePlugin.support;

import java.io.*;
import java.util.Vector;

public class XMLIgnoreWriter {
	/**
	 * FileOutputStream
	 */
	private FileOutputStream fos = null;
	
	/**
	 * PrintSteam
	 */
	private PrintStream pos = null;
	
	/**
	 * Filename to read and write to.
	 */
	private String xmlFilename;
	
	/**
	 * Saver instance
	 */
	private Saver saver;
	
	/*public XMLIgnoreWriter(String file){
		java.lang.StackTraceElement[] trace = (new Throwable()).getStackTrace();
		
		String caller = trace[1].getClassName() + "." + trace[1].getMethodName();
		
		System.out.println("Ignore XML Writer " + file + "\n" + caller + "\n");
		
		xmlFilename = file + ".ignore.xml";

	}*/
	
	public XMLIgnoreWriter(Saver s){
		saver = s;
		
		xmlFilename = saver.getIgnore();
	}
	
	/**
	 * 
	 * @return
	 */
	private Vector<IgnoredVulnerability> getIgnoredVulnerabilitiesVector(){
		
		FileInputStream fis = null;
		
		Vector<IgnoredVulnerability> ignoredVulnerabilities = new Vector<IgnoredVulnerability>();
		
		try{
			fis = new FileInputStream(xmlFilename);
			
			BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
			
			String inLine;
			
			inLine = reader.readLine();
			inLine = reader.readLine();
			
			inLine = reader.readLine();
			
			while(!inLine.equalsIgnoreCase("</Vulnerability-Ignore-List>")){                                
				IgnoredVulnerability ignoredVulnerability;
				ignoredVulnerability = new IgnoredVulnerability();
								
				// inLine is <Filename>
				inLine = reader.readLine();
				
				// inLine is <Filename> data
				inLine = reader.readLine();
				ignoredVulnerability.setFilename(inLine.trim());
				
				// inLine is </Filename>
				inLine = reader.readLine();
				
				// inLine is <LineNumber>
				inLine = reader.readLine();
				
				// inLine is <LineNumber> data
				inLine = reader.readLine();
				ignoredVulnerability.setLineNumber(Integer.valueOf(inLine.trim()).intValue());
				
				// inLine is </LineNumber>
				inLine = reader.readLine();
				
				// inLine is <Priority>
				inLine = reader.readLine();
				
				// inLine is <Priority> data
				inLine = reader.readLine();
				ignoredVulnerability.setPriority(inLine.trim());
				
				// inLine is </Priority>
				inLine = reader.readLine();
				
				// inLine is <Function>
				inLine = reader.readLine();
				
				// inLine is <Function> data
				inLine = reader.readLine();
				ignoredVulnerability.setFunctionName(inLine.trim());
				
				// inLine is </Function>
				inLine = reader.readLine();
				
				// inLine is <SourceCode>
				inLine = reader.readLine();
				
				// inLine is <SourceCode> data
				inLine = reader.readLine();
				ignoredVulnerability.setLineOfCode(inLine.trim());
				
				// inLine is </SourceCode>
				inLine = reader.readLine();
				
				// inLine is <Description>
				inLine = reader.readLine();
				
				// inLine is <Description> data
				inLine = reader.readLine();
				ignoredVulnerability.setDescription(inLine.trim());
				
				// inLine is </Description>
				inLine = reader.readLine();
				
				// inLine is <Suggestion>
				inLine = reader.readLine();
				
				// inLine is <Suggestion> data
				inLine = reader.readLine();
				ignoredVulnerability.setSuggestion(inLine.trim());
			
				// inLine is </Sugestion>
				inLine = reader.readLine();
				
				// inLine is <Pred1>
				inLine = reader.readLine();
				
				// inLine is <Pred1> data
				inLine = reader.readLine();
				ignoredVulnerability.setPredecessor1(inLine.trim());
				
				// inLine is </Pred1>
				inLine = reader.readLine();
				
				// inLine is <Pred2>
				inLine = reader.readLine();
				
				// inLine is <Pred2> data
				inLine = reader.readLine();
				ignoredVulnerability.setPredecessor2(inLine.trim());
				
				// inLine is </Pred2>
				inLine = reader.readLine();
				
				// inLine is <Pred3>
				inLine = reader.readLine();
				
				// inLine is <Pred3> data
				inLine = reader.readLine();
				ignoredVulnerability.setPredecessor3(inLine.trim());
				
				// inLine is </Pred3>
				inLine = reader.readLine();
				
				// inLine is <Suc1>
				inLine = reader.readLine();
				
				// inLine is <Suc1> data
				inLine = reader.readLine();
				ignoredVulnerability.setSuccessor1(inLine.trim());
				
				// inLine is </Suc1>
				inLine = reader.readLine();
				
				// inLine is <Suc2>
				inLine = reader.readLine();
				
				// inLine is <Suc2> data
				inLine = reader.readLine();
				ignoredVulnerability.setSuccessor2(inLine.trim());
				
				// inLine is </Suc2>
				inLine = reader.readLine();
				
				// inLine is <Suc3>
				inLine = reader.readLine();
				
				// inLine is <Suc3> data
				inLine = reader.readLine();
				ignoredVulnerability.setSuccessor3(inLine.trim());
				
				// inLine is </Suc3>
				inLine = reader.readLine();
				
				//inLine is </Vulnerbility>
				inLine = reader.readLine();
				
				ignoredVulnerabilities.add(ignoredVulnerability);
				
				inLine = reader.readLine();				
			}	
		}
		catch(Exception e){
			e.printStackTrace();
		}
		
		return ignoredVulnerabilities;		
	}
	
	@SuppressWarnings("unused")
	private char [] concatCharArrays(char [] a, char [] b){
		int lengthA = a.length;
		int lengthB = b.length;
		int count = 0;
		
		char [] newCharArray = new char [lengthA+lengthB];
				
		for(int i=0; i<lengthA; i++){
			newCharArray[count] = a[i];
			count++;
		}
		
		for(int i=0; i<lengthB; i++){
			newCharArray[count] = b[i];
			count++;
		}			
		
		return newCharArray;
	}
	
	@SuppressWarnings({ "unused", "null", "unchecked" })
	private char [] concatCharVector(char [] a, Vector b){
		int lengthA = a.length;
		int lengthB = b.size();
		int count = 0;
		
		char [] newCharArray = null;
		
		for(int i=0; i<lengthA; i++){
			newCharArray[count] = a[i];
			count++;
		}
		
		for(int i=0; i<lengthB; i++){
			newCharArray[count] = b.get(i).toString().charAt(0);
			count++;
		}		
		return newCharArray;
	}
	
	private Vector<String> concatVectors(Vector<String> a, Vector<String> b){
		int lengthA = a.size();
		int lengthB = b.size();
		int count = 0;
		
		Vector<String> newVector = new Vector<String>();
		
		for(int i=0; i<lengthA; i++){
			newVector.add(count,a.get(i));
			count++;
		}
		
		for(int i=0; i<lengthB; i++){
			newVector.add(count,b.get(i));
			count++;
		}		
		return newVector;
	}
	
	private Vector<String> toVector(String str){
		int strLength = str.length();
		Vector<String> returnVector = new Vector<String>();
				
		for(int i=0; i<strLength; i++)
			returnVector.add(i, str.substring(i,i+1));
		
		return returnVector;
	}
	
	public void appendToFile(Vulnerability newIgnoredVulnerability){
		try{
			FileInputStream fis = new FileInputStream(xmlFilename);
			
			BufferedReader bReader = new BufferedReader(new InputStreamReader(fis));
			
			Vector<String> newFileInfo = new Vector<String>();
			
			String inLine;
			
			while((inLine = bReader.readLine()) != null){
				if(inLine.equalsIgnoreCase("</Vulnerability-Ignore-List>")){
					int lineNumber = newIgnoredVulnerability.getLineNumber();
					
					char [] lineNumberChar = (String.valueOf(lineNumber)).toCharArray();
					
					Vector<String> p1, p2, p3, s1, s2, s3 = new Vector<String>();
						
					SourceReader reader = new SourceReader(saver);
					
					if(lineNumber - 1 <= 0){
						p1 = toVector("");
					}
					else{
						p1 = reader.getXMLSafeLineOfCode(lineNumber - 1);
					}
					
					if(lineNumber - 2 <= 0){
						p2 = toVector("");
					}
					else{
						p2 = reader.getXMLSafeLineOfCode(lineNumber - 2);
					}
					
					if(lineNumber - 3 <= 0){
						p3 = toVector("");
					}
					else{
						p3 = reader.getXMLSafeLineOfCode(lineNumber - 3);
					}
					
					Vector<String> predecessorInfo = new Vector<String>();
					predecessorInfo = concatVectors(predecessorInfo, toVector("<Predecessor1>\n"));
					predecessorInfo = concatVectors(predecessorInfo, p1);
					predecessorInfo = concatVectors(predecessorInfo, toVector("\n</Predecessor1>\n<Predecessor2>\n"));
					predecessorInfo = concatVectors(predecessorInfo, p2);
					predecessorInfo = concatVectors(predecessorInfo, toVector("\n</Predecessor2>\n<Predecessor3>\n"));
					predecessorInfo = concatVectors(predecessorInfo, p3);
					predecessorInfo = concatVectors(predecessorInfo, toVector("\n</Predecessor3>\n"));
					
					if(lineNumber + 1 > saver.getLines()){
						s1 = toVector("");
					}
					else{
						s1 = reader.getXMLSafeLineOfCode(lineNumber + 1);
					}
					
					if(lineNumber + 2 > saver.getLines()){
						s2 = toVector("");
					}
					else{
						s2 = reader.getXMLSafeLineOfCode(lineNumber + 2);
					}
					
					if(lineNumber + 3 > saver.getLines()){
						s3 = toVector("");
					}
					else{
						s3 = reader.getXMLSafeLineOfCode(lineNumber + 3);
					}
					
					Vector<String> successorInfo = new Vector<String>();
					successorInfo = concatVectors(successorInfo, toVector("<Successor1>\n")); 
					successorInfo = concatVectors(successorInfo, s1);
					successorInfo = concatVectors(successorInfo, toVector("\n</Successor1>\n<Successor2>\n"));
					successorInfo = concatVectors(successorInfo, s2);
					successorInfo = concatVectors(successorInfo, toVector("\n</Successor2>\n<Successor3>\n"));
					successorInfo = concatVectors(successorInfo, s3);
					successorInfo = concatVectors(successorInfo, toVector("\n</Successor3>\n"));
														
					newFileInfo = concatVectors(newFileInfo, toVector("<Vulnerability>\n<Filename>\n"));	
					newFileInfo = concatVectors(newFileInfo, toVector((newIgnoredVulnerability.getFilename())));
					newFileInfo = concatVectors(newFileInfo, toVector("\n</Filename>\n<Line-Number>\n"));					
					newFileInfo = concatVectors(newFileInfo, toVector(new String(lineNumberChar)));
					newFileInfo = concatVectors(newFileInfo, toVector("\n</Line-Number>\n<Priority>\n"));					
					newFileInfo = concatVectors(newFileInfo, toVector((newIgnoredVulnerability.getPriority())));
					newFileInfo = concatVectors(newFileInfo, toVector("\n</Priority>\n<Function>\n"));					
					newFileInfo = concatVectors(newFileInfo, toVector((newIgnoredVulnerability.getFunctionName())));
					newFileInfo = concatVectors(newFileInfo, toVector("\n</Function>\n<Source-Code>\n"));					
					newFileInfo = concatVectors(newFileInfo, (newIgnoredVulnerability.getXMLSafeLineOfCode()));
					newFileInfo = concatVectors(newFileInfo, toVector("\n</Source-Code>\n<Description>\n"));					
					newFileInfo = concatVectors(newFileInfo, (newIgnoredVulnerability.getXMLSafeDescription()));
					newFileInfo = concatVectors(newFileInfo, toVector("\n</Description>\n<Suggestion>\n"));					
					newFileInfo = concatVectors(newFileInfo, toVector((newIgnoredVulnerability.getSuggestion())));
					newFileInfo = concatVectors(newFileInfo, toVector("\n</Suggestion>\n"));
					newFileInfo = concatVectors(newFileInfo, predecessorInfo);
					newFileInfo = concatVectors(newFileInfo, successorInfo);
													
					newFileInfo = concatVectors(newFileInfo, toVector("</Vulnerability>\n"));			
				}
				
				newFileInfo = concatVectors(newFileInfo, toVector(inLine + "\n"));				
			}
			
			fos = new FileOutputStream(xmlFilename);
			pos = new PrintStream(fos);	
						
			for(int i = 0; i < newFileInfo.size(); i++){
				pos.print(newFileInfo.get(i));
			}			
		}
		catch(Exception e){
			System.out.println("Error: " + e);
		}
	}
	
	private Vector<IgnoredVulnerability> sortIgnoredVulnerabilitiesVector(Vector<IgnoredVulnerability> unsortedIgnoredVulnerabilityList){
		Vector<IgnoredVulnerability> sortedIgnoredVulnerabilityList = new Vector<IgnoredVulnerability>();
		int index = -1;
		
		while(!unsortedIgnoredVulnerabilityList.isEmpty()){
			int min = 9999;			
			int cur = 0;
			int size = unsortedIgnoredVulnerabilityList.size();
			
			if(size >= 1){
				min = ((Vulnerability)unsortedIgnoredVulnerabilityList.get(0)).getLineNumber();
				index = 0;
			}
			
			for(int i=0; i < size; i++){
				cur = ((Vulnerability)unsortedIgnoredVulnerabilityList.get(i)).getLineNumber();
				
				if(cur < min){
					index = i;
					min = cur;
				}
			}
			
			sortedIgnoredVulnerabilityList.add(unsortedIgnoredVulnerabilityList.get(index));
			unsortedIgnoredVulnerabilityList.remove(index);			
		}
		
		return sortedIgnoredVulnerabilityList;
	}
	
	private void writeXMLFile(Vector<IgnoredVulnerability> sortedIgnoredVulnerabilityList){
		try{		
			fos = new FileOutputStream(xmlFilename);
			pos = new PrintStream(fos);
		}
		catch(FileNotFoundException fnfe){
			System.err.println("Error writing to file.");
		}
		
		Vector<String> toWrite = new Vector<String>();
		
		toWrite = toVector("<?xml version=\"1.0\"?>\n");
		toWrite = concatVectors(toWrite, toVector("<Vulnerability-Ignore-List>\n"));
		
		for(int i=0; i < sortedIgnoredVulnerabilityList.size(); i++){
			toWrite = concatVectors(toWrite, toVector("<Vulnerability>\n"));
			toWrite = concatVectors(toWrite, toVector("<Filename>\n"));
			toWrite = concatVectors(toWrite, toVector(sortedIgnoredVulnerabilityList.get(i).getFilename()));
			toWrite = concatVectors(toWrite, toVector("\n</Filename>\n<Line-Number>\n"));
			
			int lineNumber = sortedIgnoredVulnerabilityList.get(i).getLineNumber();			
			char [] lineNumberChar = (String.valueOf(lineNumber)).toCharArray();
			
			toWrite = concatVectors(toWrite, toVector(new String(lineNumberChar)));
			toWrite = concatVectors(toWrite, toVector("\n</Line-Number>\n"));
			toWrite = concatVectors(toWrite, toVector("<Priority>\n"));
			toWrite = concatVectors(toWrite, toVector(sortedIgnoredVulnerabilityList.get(i).getPriority()));
			toWrite = concatVectors(toWrite, toVector("\n</Priority>\n"));
			toWrite = concatVectors(toWrite, toVector("<Function>\n"));
			toWrite = concatVectors(toWrite, toVector(sortedIgnoredVulnerabilityList.get(i).getFunctionName()));
			toWrite = concatVectors(toWrite, toVector("\n</Function>\n"));
			toWrite = concatVectors(toWrite, toVector("<Source-Code>\n"));
			toWrite = concatVectors(toWrite, sortedIgnoredVulnerabilityList.get(i).getXMLSafeLineOfCode());
			toWrite = concatVectors(toWrite, toVector("\n</Source-Code>\n<Description>\n"));
			toWrite = concatVectors(toWrite, sortedIgnoredVulnerabilityList.get(i).getXMLSafeDescription());
			toWrite = concatVectors(toWrite, toVector("\n</Description>\n<Suggestion>\n"));
			toWrite = concatVectors(toWrite, toVector(sortedIgnoredVulnerabilityList.get(i).getSuggestion()));
			toWrite = concatVectors(toWrite, toVector("\n</Suggestion>\n<Predecessor1>\n"));
			toWrite = concatVectors(toWrite, sortedIgnoredVulnerabilityList.get(i).getXMLSafePredecessor1());
			toWrite = concatVectors(toWrite, toVector("\n</Predecessor1>\n<Predecessor2>\n"));
			toWrite = concatVectors(toWrite, sortedIgnoredVulnerabilityList.get(i).getXMLSafePredecessor2());
			toWrite = concatVectors(toWrite, toVector("\n</Predecessor2>\n<Predecessor3>\n"));;
			toWrite = concatVectors(toWrite, sortedIgnoredVulnerabilityList.get(i).getXMLSafePredecessor3());
			toWrite = concatVectors(toWrite, toVector("\n</Predecessor3>\n<Successor1>\n"));
			toWrite = concatVectors(toWrite, sortedIgnoredVulnerabilityList.get(i).getXMLSafeSuccessor1());
			toWrite = concatVectors(toWrite, toVector("\n</Successor1>\n<Successor2>\n"));
			toWrite = concatVectors(toWrite, sortedIgnoredVulnerabilityList.get(i).getXMLSafeSuccessor2());
			toWrite = concatVectors(toWrite, toVector("\n</Successor2>\n<Successor3>\n"));
			toWrite = concatVectors(toWrite, sortedIgnoredVulnerabilityList.get(i).getXMLSafeSuccessor3());
			toWrite = concatVectors(toWrite, toVector("\n</Successor3>\n</Vulnerability>\n"));
		}
		
		toWrite = concatVectors(toWrite, toVector("</Vulnerability-Ignore-List>"));
				
		for(int i = 0; i < toWrite.size(); i++){
			pos.print(toWrite.get(i).toString());
		}	
	}
	
	public void writeBlankXML(){
		try{
			File file = new File(xmlFilename);
					
			file.createNewFile();
			fos = new FileOutputStream(xmlFilename);
			pos = new PrintStream(fos);
			pos.println("<?xml version=\"1.0\"?>");
			pos.println("<Vulnerability-Ignore-List>");				
			pos.println("</Vulnerability-Ignore-List>");
			pos.close();
			fos.close();		
		}
		catch(Exception e){
			System.out.println("Error: " + e);
		}
	}
	
	public void writeXML(Vulnerability vulnerability){
		try{
			File file = new File(xmlFilename);
			
			if(!file.exists()){
				file.createNewFile();
				fos = new FileOutputStream(xmlFilename);
				pos = new PrintStream(fos);
				pos.println("<?xml version=\"1.0\"?>");
				pos.println("<Vulnerability-Ignore-List>");				
				pos.println("</Vulnerability-Ignore-List>");
				pos.flush();
				pos.close();
				fos.close();
			}
		}
		catch(Exception e){
			System.out.println("Error: " + e);
		}
		
		appendToFile(vulnerability);
		Vector<IgnoredVulnerability> ingoredVulnerabilities = getIgnoredVulnerabilitiesVector();
		
		Vector<IgnoredVulnerability> sortedIngoredVulnerabilities = sortIgnoredVulnerabilitiesVector(ingoredVulnerabilities);
		writeXMLFile(sortedIngoredVulnerabilities);			
	}
}
